import { atom, createStore as cs, useAtom } from "jotai";
import { IModel } from "./types";

export const store = cs();
export const atomMap = {};
export const actionsMap = {};
export const loadingState = {
  effects: {},
};

export function createStore<T extends Object, F extends Object>(
  models: IModel<T, F>
) {
  Object.keys(atomMap).forEach((namespace) => {
    delete atomMap[namespace];
  });
  Object.keys(actionsMap).forEach((namespace) => {
    delete actionsMap[namespace];
  });
  addStores(models);
  const loadingAtom = atom(loadingState);
  atomMap["loading"] = loadingAtom;
  store.set(loadingAtom, loadingState);
  return store;
}

export function addStores<T extends Object, F extends Object>(
  models: IModel<T, F>
) {
  const { states, actions } = models || {};
  Object.keys(actions).forEach((namespace) => {
    actionsMap[namespace] = actions[namespace];
  });
  Object.keys(states).forEach((namespace) => {
    const state = states[namespace];
    const stateAtom = atom(state);
    atomMap[namespace] = stateAtom;
    store.set(stateAtom, state);
  });
  return store;
}

export function updateState<T extends Object>(namespace: string, state: T) {
  const atom = atomMap[namespace];
  const atomState = (store.get(atom) || {}) as any;
  store.set(atom, {
    ...atomState,
    ...state,
  });
}

export function updateLoadingState<T extends Object>(state: T) {
  const atom = atomMap["loading"];
  const atomState = (store.get(atom) || {}) as any;
  store.set(atom, {
    effects: {
      ...atomState.effects,
      ...state,
    },
  });
}
